# coding=utf-8

import os
import multiprocessing
import datetime
import shutil
import logging
import tarfile
import xlwt
import xml.dom.minidom
from components.guide import guide
from managers.globalarea import app_config
from services.resourcesservice import resourcesservice
from persistents import RedisServices
from components.objs import Task_In_Redis
from utils.TimeUtils import calc_exec_during_timing, get_during_seconds_from_now, get_during_hours, \
    get_during_days_to_now
from utils.test import filter_fatal_signal, filter_fatal_exception, filter_anr, crash_anr_analysis_obj
from workflow import TaskBuild2MonkeyFlow

lock = multiprocessing.Lock()


class TaskMonkeyTest(object):

    def __init__(self):
        self.resource = resourcesservice()
        self.rds_handler = RedisServices()
        self.task_prefix = 'task_monkey_'
        self.t_prefix = 'task_'
        self.expired_key_prefix = 'monkey_'
        self.work_flow_record = {}
        self.datestr = str(datetime.datetime.now().date())

    def private_logger(self, params):
        paraminredis = self.rds_handler.hgetall(str(params))
        result_dir = paraminredis[Task_In_Redis.result_dir] + '/' + str(datetime.datetime.now().date())
        if not os.path.exists(result_dir):
            os.mkdir(result_dir)
        result_dir = result_dir + '/' + paraminredis[Task_In_Redis.product_name_cn]
        if not os.path.exists(result_dir):
            os.mkdir(result_dir)
        self.resultpath = result_dir + '/'
        path = result_dir + '/' + paraminredis[Task_In_Redis.product_name_cn] + '_' + str(
            datetime.datetime.now()).replace(' ', '_') + '.log'
        tag = str(datetime.datetime.now()).replace(' ', '_') + '_' + str(multiprocessing.current_process().pid)
        self.logger = logging.getLogger(tag)
        consoleHandler = logging.StreamHandler()
        consoleHandler.setLevel(logging.DEBUG)
        # path = './output/logs/TaskMonkeyTest_' + tag + '.log'
        self.work_flow_record[TaskBuild2MonkeyFlow.log_path] = path
        fileHandler = logging.FileHandler(path, encoding='utf-8')
        fileHandler.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            '%(asctime)s-%(processName)s-%(process)d-%(filename)s-%(funcName)s-%(levelname)s-%(lineno)d - %(message)s')
        consoleHandler.setFormatter(formatter)
        fileHandler.setFormatter(formatter)
        self.logger.setLevel(logging.DEBUG)
        self.logger.addHandler(consoleHandler)
        self.logger.addHandler(fileHandler)

    def __call__(self, *args, **kwargs):
        self.private_logger(*args, **kwargs)
        self.logger.info("called at %s " % str(datetime.datetime.now()))
        self.logger.info("called param is %s, %s " % (str(args), str(kwargs)))
        self.monkey_test_worker(*args, **kwargs)

    def next_task(self, task_key, param):
        ex_name = task_key.lstrip(self.t_prefix)
        ex_time = calc_exec_during_timing(param[0], param[1], param[2], param[3], param[4])
        if app_config.env:
            if param[0] != '1':
                self.logger.debug("任务%s下一次的执行将在%s小时后" % (task_key, str(ex_time / 3600.0)))
                self.logger.info('expired time in seconds %s' % ex_time)
                self.rds_handler.setex(ex_name, ex_time)
                self.work_flow_record[TaskBuild2MonkeyFlow.if_next] = True
            else:
                self.logger.debug("不是周期任务")
                self.work_flow_record[TaskBuild2MonkeyFlow.if_next] = False
        else:
            self.rds_handler.setex(ex_name, 36000)

    def record_task(self, his, lock, sn):
        lock.acquire()
        pid = self.work_flow_record[TaskBuild2MonkeyFlow.pid]
        try:
            record = eval(str(self.rds_handler.hget(app_config.task_exec_history, self.datestr)))
            if record != "None" and record != '' and record is not None:
                if len([1 for info in record if sn in info[TaskBuild2MonkeyFlow.product_of_device]]) > 0 and len(
                        [1 for info in record if str(pid) == str(info[TaskBuild2MonkeyFlow.pid])]) > 0:
                    record[[1 if sn in info[TaskBuild2MonkeyFlow.product_of_device] and str(pid) == str(
                        info[TaskBuild2MonkeyFlow.pid]) else 0 for info in record].index(
                        1)] = his
                else:
                    record.append(his)
            else:
                record = []
                record.append(his)
            self.rds_handler.hset(app_config.task_exec_history, self.datestr, str(record))
        finally:
            lock.release()

    def analysis_crash_and_anr(self, crash_files, anr_files):
        crash_info = []
        if crash_files:
            crash_info.extend(filter_fatal_signal(crash_files))
            crash_info.extend(filter_fatal_exception(crash_files))
        self.work_flow_record[TaskBuild2MonkeyFlow.crash_info] = str(crash_info)
        anr_info = []
        if anr_files:
            anr_info.extend(filter_anr(anr_files))
        self.work_flow_record[TaskBuild2MonkeyFlow.anr_info] = str(anr_info)
        crash_and_anr = []
        crash_and_anr.extend(crash_info)
        crash_and_anr.extend(anr_info)
        # print crash_and_anr
        if crash_and_anr:
            wb = xlwt.Workbook(encoding='utf-8')
            ws = wb.add_sheet('CRASH_ANR Report')
            row_c = 0
            for n, k in enumerate(crash_anr_analysis_obj.list_of_title):
                ws.write(row_c, n, crash_anr_analysis_obj.dict_desc[k])
            row_c += 1
            for d in crash_and_anr:
                self.logger.info(d)
                for n, k in enumerate(crash_anr_analysis_obj.list_of_title):
                    ws.write(row_c, n, d[k])
                row_c += 1
            print self.resultpath
            wb.save(self.resultpath + 'CRASH_ANR_Report.xls')

    def zip_task_files(self, taskfilepath):
        logging.info(taskfilepath)
        with tarfile.open(os.path.abspath(taskfilepath) + ".tar.gz", "w:gz") as tar:
            tar.add(taskfilepath, arcname=os.path.basename(taskfilepath))
        self.work_flow_record[TaskBuild2MonkeyFlow.downloadfile] = taskfilepath + ".tar.gz"
        self.work_flow_record[TaskBuild2MonkeyFlow.downloadfilename] = os.path.basename(taskfilepath + ".tar.gz")

    def monkey_test_worker(self, params):
        self.work_flow_record[TaskBuild2MonkeyFlow.pid] = multiprocessing.current_process().pid
        self.work_flow_record[TaskBuild2MonkeyFlow.build_result] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.build_url] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.rom_path] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.flash_result] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.guide_jump_result] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.flash_result] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.error_info] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.monkey_exec_cmd] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.mind_package] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.begin_time_of_monkey_test] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.end_time_of_monkey_test] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.hours_of_monkey_test] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.monkey_exec_log_path] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.crash_count] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.crash_files_path_list] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.anr_count] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.anr_files_path_list] = 'Na'
        self.work_flow_record[TaskBuild2MonkeyFlow.error_info] = []
        self.work_flow_record[TaskBuild2MonkeyFlow.if_next] = "Na"
        self.work_flow_record[TaskBuild2MonkeyFlow.done] = "begin-"
        self.work_flow_record[TaskBuild2MonkeyFlow.status] = "begin"
        result = str(os.getppid()) + "_" + str(os.getpid())
        pname = multiprocessing.current_process().name
        self.logger.info("执行%s的任务" % (pname,))
        self.logger.info("执行入参:" + str(params))
        taskinfo = str(params)
        paraminredis = self.rds_handler.hgetall(str(params))
        sn = paraminredis[Task_In_Redis.sn]
        self.work_flow_record[TaskBuild2MonkeyFlow.sup_task_name] = paraminredis[Task_In_Redis.task_name]
        self.work_flow_record[TaskBuild2MonkeyFlow.sub_task_name] = paraminredis[Task_In_Redis.sub_task_name]
        mi_account_name = paraminredis[Task_In_Redis.mi_account_name]
        listparam = [paraminredis[i] for i in Task_In_Redis.monkey_task_exec]
        self.next_task(params, listparam[-5:])
        params = listparam[:-5]
        self.work_flow_record[TaskBuild2MonkeyFlow.product_of_device] = '_'.join(params[:4]) + '_' + paraminredis[
            Task_In_Redis.product_name_cn]
        if str(params[4]) == "1":
            # pass
            self.logger.info("执行%s的任务. 有3此构建ROM包的机会" % (pname,))
            # 给三次构建rom包的机会，已防止构建失败和构建超市
            status = False
            url = None
            if app_config.env:
                self.work_flow_record[TaskBuild2MonkeyFlow.done] += "building-"
                self.work_flow_record[TaskBuild2MonkeyFlow.status] = "building"
                self.record_task(self.work_flow_record, lock, sn)
                for trytimes in xrange(3):
                    self.logger.info("执行%s的任务. 尝试第%s次构建ROM包" % (pname, trytimes))
                    status, url = self.resource.getRom(params, self.logger, mi_account_name)
                    self.logger.info('%s, %s' % (str(status), str(url)))
                    if status and url is not None:
                        self.work_flow_record[TaskBuild2MonkeyFlow.done] += "built-"
                        self.work_flow_record[TaskBuild2MonkeyFlow.status] = "built"
                        self.record_task(self.work_flow_record, lock, sn)
                        self.logger.info("执行%s的任务, 尝试第%s次构建成功" % (pname, trytimes))
                        break
                self.work_flow_record[TaskBuild2MonkeyFlow.build_result] = status
                self.work_flow_record[TaskBuild2MonkeyFlow.build_url] = url
            else:
                status = True
                url = "http://corgi.pt.miui.com/open-api/build/905861/out/andromeda_images_1.1.1_20190415.0000.00_9.0_cn_8bafb75d87.tgz"
            if status:
                # guide(self.resource.getDeviceBySn(params[0])).handleGuidePage(self.logger)
                if not url.startswith('http://'):
                    url = "http://" + url
                self.logger.info("获取ROM包的url： %s" % (str(url),))
                # 构建成功，下载并解压到对应目录
                self.work_flow_record[TaskBuild2MonkeyFlow.done] += "downloading-"
                self.work_flow_record[TaskBuild2MonkeyFlow.status] = "downloading"
                self.record_task(self.work_flow_record, lock, sn)
                flashscriptpath = self.resource.my_localsystem.downloadRomAndTarOpen(url, self.logger)
                self.work_flow_record[TaskBuild2MonkeyFlow.rom_path] = flashscriptpath
                self.work_flow_record[TaskBuild2MonkeyFlow.done] += "downloaded-flashing-"
                self.work_flow_record[TaskBuild2MonkeyFlow.status] = "flashing"
                self.record_task(self.work_flow_record, lock, sn)
                tims = 0
                self.logger.info("执行%s的任务, 有2次刷机机会" % (pname,))
                # 给两次刷包机会，应对可能存在的刷包问题
                while True:
                    if tims > 1:
                        self.work_flow_record[TaskBuild2MonkeyFlow.flash_result] = False
                        self.work_flow_record[TaskBuild2MonkeyFlow.error_info].append("刷机和跳过引导页面2次失败")
                        break
                    try:
                        self.logger.info("执行%s的任务, 开始刷机" % (pname,))
                        # 刷机
                        flashresult, desc = self.resource.getDeviceBySn(params[0]).flashdevice(self.logger,
                                                                                               flashscriptpath=flashscriptpath)
                        if flashresult:
                            self.work_flow_record[TaskBuild2MonkeyFlow.flash_result] = True
                            # 跳过引导页
                            self.logger.info("执行%s的任务, 开始处理引导页" % (pname,))
                            times_guide = 0
                            flag_jump_guide = False
                            while True:
                                if times_guide > 1:
                                    break
                                if guide(self.resource.getDeviceBySn(params[0])).handleGuidePage(self.logger):
                                    self.logger.info("执行%s的任务, 刷机成功，已跳过引导，进入手机主界面。" % (pname,))
                                    result += "1.刷机成功，已跳过引导，进入手机主界面。"
                                    self.work_flow_record[TaskBuild2MonkeyFlow.guide_jump_result] = True
                                    flag_jump_guide = True
                                    break
                                times_guide += 1
                                self.logger.info("执行%s的任务, 刷机成功，跳过引导页第%s次失败。" % (pname, str(times_guide)))
                            if flag_jump_guide:
                                break
                            else:
                                if times_guide > 1:
                                    self.work_flow_record[TaskBuild2MonkeyFlow.guide_jump_result] = False
                                    self.work_flow_record[TaskBuild2MonkeyFlow.error_info].append("跳过引导界面失败")
                                    self.logger.info("执行%s的任务, 跳过guide失败。")
                                    break
                        else:
                            if desc in ["DEVICENOTREADY", "FLASHERROR", "DEVICENOTFOUND", "DEVICENOTREADYAFTERFLASH",
                                        "DEVICENOTFOUNDAFTERFLASH"]:
                                break
                            if tims > 0:
                                self.work_flow_record[TaskBuild2MonkeyFlow.flash_result] = False
                                self.work_flow_record[TaskBuild2MonkeyFlow.error_info].append("刷机失败")
                                self.logger.info("执行%s的任务, 刷机失败。")
                                break
                            tims += 1
                    except Exception, e:
                        self.logger.info("执行%s的任务, Exceptions %s。" % (pname, str(e.message)))
                        tims += 1
                        continue
                    except xml.parsers.expat.ExpatError, e:
                        self.logger.info("执行%s的任务, ExpatError %s。" % (pname, str(e.message)))
                        tims += 1
                        continue
                if self.work_flow_record[TaskBuild2MonkeyFlow.flash_result]:
                    self.work_flow_record[TaskBuild2MonkeyFlow.done] += "flashed-"
                    self.work_flow_record[TaskBuild2MonkeyFlow.status] = "flashed"
                    self.record_task(self.work_flow_record, lock, sn)
                self.logger.info("执行%s的任务, 清除下载的rom文件和解压缩后的文件" % (pname,))
                # '清除下载的rom文件和解压缩后的文件'
                romfile = url.split('/')[-1]
                romtarfile = romfile.strip('.tgz')
                self.logger.info('清除的rom文件和文件夹是：%s | %s' % (str(romfile), str(romtarfile)))
                if os.path.exists('./' + romfile):
                    os.remove('./' + romfile)
                if os.path.exists('./' + romtarfile):
                    shutil.rmtree('./' + romtarfile)
                self.logger.info("执行%s的任务, 下载的rom文件和解压缩后的文件是否存在 %s %s" % (
                    pname, str(os.path.exists('./' + romfile)), str(os.path.exists('./' + romtarfile))))
            else:
                self.work_flow_record[TaskBuild2MonkeyFlow.error_info].append("build rom error: %s" % status)
                if app_config.env:
                    return

        if not len([d['sn'] for d in self.resource.getAllDevicesWorkState() if d['sn'] == params[0]]):
            self.logger.info("设备%s不在线or不在正常状态" % (params[0],))
            self.work_flow_record[TaskBuild2MonkeyFlow.error_info].append("设备%s不在线or不在正常状态" % (params[0],))
            # 删除对应设备的monkey定时任务
            devices_not_ok = self.rds_handler.keys(app_config.expired_key_prefix + params[0] + '*')
            [self.rds_handler.delete(k) for k in devices_not_ok]
            return

        if str(params[5]) == "1":
            self.logger.info("执行%s的任务, 开始monkey测试" % (pname,))
            # monkey测试
            monkey_params = params[-2].split(' ')
            throttle = int(monkey_params[monkey_params.index('--throttle') + 1] if monkey_params[
                monkey_params.index('--throttle') + 1] else 300)
            eventcount_init = monkey_params[monkey_params.index('--bugreport') + 1]
            if app_config.env:
                if listparam[-5] != '1':
                    if listparam[-3] == '':
                        ex_seconds = calc_exec_during_timing(listparam[-5], listparam[-4], listparam[-3], listparam[-2],
                                                             listparam[-1])
                    else:
                        h, m, s = listparam[-3].split('-')[1].lstrip(' ').split(':')
                        ex_seconds = get_during_seconds_from_now(0, h, m, s)
                        if ex_seconds < 30:
                            self.logger.info("没有过多的时间进行monkey测试了: %s" % str(ex_seconds))
                            return
                else:
                    ex_seconds = int(listparam[-2]) * 3600
                eventcount = int(ex_seconds * (1000.0 / throttle))
            else:
                ex_seconds = 1220
                eventcount = 1000
            self.logger.info("执行的monkey失效秒数: %s" % str(ex_seconds))
            monkeycmd = params[-2].replace(eventcount_init, str(eventcount * 10))
            # seedno = random.randint(100, 1000)
            # monkeycmd = monkeycmd.replace('1000', str(seedno))
            self.logger.info("执行的monkey指令是: %s" % str(monkeycmd))
            self.work_flow_record[TaskBuild2MonkeyFlow.monkey_exec_cmd] = monkeycmd
            pkgs = monkeycmd.split(' -v ')[0].strip("'monkey")
            mind_package = ''.join([p + '\n' for p in pkgs.split(' -p ') if p != '']) if pkgs else 'all'
            self.work_flow_record[TaskBuild2MonkeyFlow.mind_package] = mind_package
            self.resource.getDeviceBySn(params[0]).killall_monkey()
            self.resource.getDeviceBySn(params[0]).setScreenOn()
            self.work_flow_record[TaskBuild2MonkeyFlow.done] += "monkeytesting-"
            self.work_flow_record[TaskBuild2MonkeyFlow.status] = "monkeytesting"
            t0 = str(datetime.datetime.now())
            self.work_flow_record[TaskBuild2MonkeyFlow.begin_time_of_monkey_test] = t0
            self.record_task(self.work_flow_record, lock, sn)
            monkey_result = self.resource.getDeviceBySn(params[0]).monkey_test(monkeycmd, taskinfo, ex_seconds,
                                                                               self.logger, self.resultpath)
            self.logger.info("执行的monkey结果: %s" % str(monkey_result))
            t1 = str(datetime.datetime.now())
            self.work_flow_record[TaskBuild2MonkeyFlow.end_time_of_monkey_test] = t1
            self.work_flow_record[TaskBuild2MonkeyFlow.hours_of_monkey_test] = get_during_hours(t1, t0)
            self.work_flow_record[TaskBuild2MonkeyFlow.monkey_exec_log_path] = monkey_result[1]
            self.work_flow_record[TaskBuild2MonkeyFlow.done] += "monkeytested-"
            self.work_flow_record[TaskBuild2MonkeyFlow.status] = "monkeytested"
            if monkey_result[0]:
                crash_files_num, crash_files_path_list, anr_files_num, anr_files_path_list = self.resource.getDeviceBySn(
                    params[0]).pull_crash_and_anr_log(self.logger, self.resultpath, taskinfo=taskinfo)
                self.logger.info("crash and anr infos: %s, %s, %s, %s" % (
                    str(crash_files_num), str(crash_files_path_list), str(anr_files_num), str(anr_files_path_list)))
                self.work_flow_record[TaskBuild2MonkeyFlow.crash_count] = crash_files_num
                self.work_flow_record[TaskBuild2MonkeyFlow.crash_files_path_list] = crash_files_path_list
                self.work_flow_record[TaskBuild2MonkeyFlow.anr_count] = anr_files_num
                self.work_flow_record[TaskBuild2MonkeyFlow.anr_files_path_list] = anr_files_path_list
                self.logger.info("执行%s的任务, 执行monkey测试结束" % (pname,))
                result += "2. 执行monkey测试结束。"
        self.work_flow_record[TaskBuild2MonkeyFlow.done] += "analysis-"
        self.work_flow_record[TaskBuild2MonkeyFlow.status] = "analysis"
        self.record_task(self.work_flow_record, lock, sn)
        self.analysis_crash_and_anr(crash_files_path_list, anr_files_path_list)
        self.zip_task_files(self.resultpath.rstrip('/'))
        self.work_flow_record[TaskBuild2MonkeyFlow.done] += "end"
        self.work_flow_record[TaskBuild2MonkeyFlow.status] = "end"
        self.record_task(self.work_flow_record, lock, sn)
        # self.rds_handler.setex('report_' + str(datetime.datetime.now()), 2)
    # 充值使用的机型状态
    # self.resource.resetDeviceWorkState(params[0])


class TaskHandlerTerminated(object):

    def __init__(self):
        self.resource = resourcesservice()
        self.rds_handler = RedisServices()
        self.work_flow_record = {}
        self.datestr = ''
        self.pid = ''

    def private_logger(self, params):
        pid, self.datestr = params
        self.pid = pid
        record = eval(str(self.rds_handler.hget(app_config.task_exec_history, self.datestr)))
        print record
        if record != "None" and record != '' and record is not None:
            if len([1 for info in record if str(pid) == str(info[TaskBuild2MonkeyFlow.pid])]) > 0:
                print record[0], [1 if str(pid) == str(info[TaskBuild2MonkeyFlow.pid]) else 0 for info in record].index(
                    1)
                self.work_flow_record = record[
                    [1 if str(pid) == str(info[TaskBuild2MonkeyFlow.pid]) else 0 for info in record].index(1)]
        print self.work_flow_record
        tag = str(datetime.datetime.now()).replace(' ', '_') + '_' + str(multiprocessing.current_process().pid)
        self.logger = logging.getLogger(tag)
        consoleHandler = logging.StreamHandler()
        consoleHandler.setLevel(logging.DEBUG)
        path = self.work_flow_record[TaskBuild2MonkeyFlow.log_path]
        fileHandler = logging.FileHandler(path, encoding='utf-8')
        fileHandler.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            '%(asctime)s-%(processName)s-%(process)d-%(filename)s-%(funcName)s-%(levelname)s-%(lineno)d - %(message)s')
        consoleHandler.setFormatter(formatter)
        fileHandler.setFormatter(formatter)
        self.logger.setLevel(logging.DEBUG)
        self.logger.addHandler(consoleHandler)
        self.logger.addHandler(fileHandler)

    def __call__(self, *args, **kwargs):
        self.private_logger(*args, **kwargs)
        self.logger.info("task被提前终止,现在进行收尾处理")
        self.logger.info("called at %s " % str(datetime.datetime.now()))
        self.logger.info("called param is %s, %s " % (str(args), str(kwargs)))
        self.monkey_test_worker(*args, **kwargs)

    def record_task(self, his, lock, sn):
        lock.acquire()
        pid = self.pid
        try:
            record = eval(str(self.rds_handler.hget(app_config.task_exec_history, self.datestr)))
            if record != "None" and record != '' and record is not None:
                self.logger.debug([1 for info in record if sn in info[TaskBuild2MonkeyFlow.product_of_device]])
                self.logger.debug([1 for info in record if str(pid) == str(info[TaskBuild2MonkeyFlow.pid])])
                if len([1 for info in record if sn in info[TaskBuild2MonkeyFlow.product_of_device]]) > 0 and len(
                        [1 for info in record if str(pid) == str(info[TaskBuild2MonkeyFlow.pid])]) > 0:
                    record[[1 if sn in info[TaskBuild2MonkeyFlow.product_of_device] and str(pid) == str(
                        info[TaskBuild2MonkeyFlow.pid]) else 0 for info in record].index(
                        1)] = his
                else:
                    record.append(his)
            else:
                record = []
                record.append(his)
            self.rds_handler.hset(app_config.task_exec_history, self.datestr, str(record))
        finally:
            lock.release()

    def analysis_crash_and_anr(self, crash_files, anr_files):
        crash_info = []
        crash_info.extend(filter_fatal_signal(crash_files))
        crash_info.extend(filter_fatal_exception(crash_files))
        self.work_flow_record[TaskBuild2MonkeyFlow.crash_info] = crash_info
        anr_info = []
        anr_info.extend(filter_anr(anr_files))
        self.work_flow_record[TaskBuild2MonkeyFlow.anr_info] = anr_info
        crash_and_anr = []
        crash_and_anr.extend(crash_info)
        crash_and_anr.extend(anr_info)
        # print crash_and_anr
        if crash_and_anr:
            wb = xlwt.Workbook(encoding='utf-8')
            ws = wb.add_sheet('CRASH_ANR Report')
            row_c = 0
            for n, k in enumerate(crash_anr_analysis_obj.list_of_title):
                ws.write(row_c, n, crash_anr_analysis_obj.dict_desc[k])
            row_c += 1
            for d in crash_and_anr:
                self.logger.info(d)
                for n, k in enumerate(crash_anr_analysis_obj.list_of_title):
                    ws.write(row_c, n, d[k])
                row_c += 1
            print self.resultpath
            wb.save(self.resultpath + 'CRASH_ANR_Report.xls')

    def zip_task_files(self, taskfilepath):
        logging.info(taskfilepath)
        with tarfile.open(os.path.abspath(taskfilepath) + ".tar.gz", "w:gz") as tar:
            tar.add(taskfilepath, arcname=os.path.basename(taskfilepath))
        self.work_flow_record[TaskBuild2MonkeyFlow.downloadfile] = taskfilepath + ".tar.gz"
        self.work_flow_record[TaskBuild2MonkeyFlow.downloadfilename] = os.path.basename(taskfilepath + ".tar.gz")

    def monkey_test_worker(self, params):

        logging.info(self.work_flow_record)
        sn = self.work_flow_record[TaskBuild2MonkeyFlow.product_of_device].split('_')[0]
        t0 = self.work_flow_record[TaskBuild2MonkeyFlow.begin_time_of_monkey_test]
        taskinfo = self.work_flow_record[TaskBuild2MonkeyFlow.sub_task_name]
        self.work_flow_record[TaskBuild2MonkeyFlow.done] += "monkeytested-terminated-"
        self.work_flow_record[TaskBuild2MonkeyFlow.status] = "terminated"
        self.record_task(self.work_flow_record, lock, sn)
        t1 = str(datetime.datetime.now())
        self.resultpath = os.path.dirname(self.work_flow_record[TaskBuild2MonkeyFlow.log_path]) + '/'
        cmd_monkey = self.work_flow_record[TaskBuild2MonkeyFlow.monkey_exec_cmd]
        self.work_flow_record[TaskBuild2MonkeyFlow.end_time_of_monkey_test] = t1
        self.work_flow_record[TaskBuild2MonkeyFlow.hours_of_monkey_test] = get_during_hours(t1, t0)
        log_of_monkey = self.resource.getDeviceBySn(sn).terminate_monkey_logfile_pull(cmd_monkey, self.resultpath,
                                                                                      taskinfo, self.logger)
        self.work_flow_record[TaskBuild2MonkeyFlow.monkey_exec_log_path] = log_of_monkey
        crash_files_num, crash_files_path_list, anr_files_num, anr_files_path_list = self.resource.getDeviceBySn(
            sn).pull_crash_and_anr_log(self.logger, self.resultpath, taskinfo=taskinfo)
        self.logger.info("crash and anr infos: %s, %s, %s, %s" % (
            str(crash_files_num), str(crash_files_path_list), str(anr_files_num), str(anr_files_path_list)))
        self.work_flow_record[TaskBuild2MonkeyFlow.crash_count] = crash_files_num
        self.work_flow_record[TaskBuild2MonkeyFlow.crash_files_path_list] = crash_files_path_list
        self.work_flow_record[TaskBuild2MonkeyFlow.anr_count] = anr_files_num
        self.work_flow_record[TaskBuild2MonkeyFlow.anr_files_path_list] = anr_files_path_list
        self.work_flow_record[TaskBuild2MonkeyFlow.done] += "analysis-"
        self.work_flow_record[TaskBuild2MonkeyFlow.status] = "analysis"
        self.record_task(self.work_flow_record, lock, sn)
        self.analysis_crash_and_anr(crash_files_path_list, anr_files_path_list)
        self.zip_task_files(self.resultpath.rstrip('/'))
        self.work_flow_record[TaskBuild2MonkeyFlow.done] += "end"
        self.work_flow_record[TaskBuild2MonkeyFlow.status] = "end"
        self.record_task(self.work_flow_record, lock, sn)
        # self.rds_handler.setex('report_' + str(datetime.datetime.now()), 2)


class TaskTimingReport(object):

    def private_logger(self, params):
        pass
        # tag = str(datetime.datetime.now()).replace(' ', '_') + '_' + str(multiprocessing.current_process().pid)
        # self.logger = logging.getLogger(tag)
        # consoleHandler = logging.StreamHandler()
        # consoleHandler.setLevel(logging.DEBUG)
        # path = './output/ExcelReport_' + tag + '.log'
        # fileHandler = logging.FileHandler(path, encoding='utf-8')
        # fileHandler.setLevel(logging.DEBUG)
        # formatter = logging.Formatter(
        #     '%(asctime)s-%(processName)s-%(process)d-%(filename)s-%(funcName)s-%(levelname)s-%(lineno)d - %(message)s')
        # consoleHandler.setFormatter(formatter)
        # fileHandler.setFormatter(formatter)
        # self.logger.setLevel(logging.DEBUG)
        # self.logger.addHandler(consoleHandler)
        # self.logger.addHandler(fileHandler)

    def __call__(self, *args, **kwargs):

        self.private_logger(*args, **kwargs)
        self.rds_handler = RedisServices()
        self.generalReport(*args, **kwargs)

    def next_task(self):
        exec_timing = str((datetime.datetime.now() - datetime.timedelta(days=-1)).date()) + " 08:00:00"
        ex_seconds = int((datetime.datetime.strptime(exec_timing,
                                                     "%Y-%m-%d %H:%M:%S") - datetime.datetime.now()).total_seconds())
        if app_config.env:
            # self.logger.info("next report after %s hours" % (str(ex_seconds / 3600),))
            self.rds_handler.setex('report_' + str(datetime.datetime.now()), ex_seconds)
        else:
            self.rds_handler.setex('report_' + str(datetime.datetime.now()), 600)

    def generalReport(self, param):
        self.next_task()
        records = self.rds_handler.hgetall(app_config.task_exec_history)
        if records:
            wb = xlwt.Workbook(encoding='utf-8')
            ws = wb.add_sheet('Monkey Test Report')
            row_c = 0
            column_c = 0
            ws.write(row_c, column_c, u'日期')
            for n, k in enumerate(TaskBuild2MonkeyFlow.list_culomn):
                ws.write(row_c, n + 1, TaskBuild2MonkeyFlow.dict_desc[k])
            row_c += 1
            for d in xrange(10):
                k_d = str((datetime.datetime.now() - datetime.timedelta(days=d)).date())
                if k_d in records.keys():
                    ws.write(row_c, 0, k_d)
                    for r in eval(records[k_d]):
                        for n, k in enumerate(TaskBuild2MonkeyFlow.list_culomn):
                            ws.write(row_c, n + 1, r[k])
                        row_c += 1
            wb.save('./output/' + str(datetime.datetime.now().date()) + '_Monkey_Test_Report.xls')
